#include "mymainwindow.h"
#include "ui_mymainwindow.h"
#include <QDialog>
#include <QFileDialog>
#include <QDebug>
#include <QTextCodec>
#include <QListView>
#include <QFileInfo>
#include <QMessageBox>
#include <QDataStream>
#include "../include/temu.h"


extern CPU_state cpu;
extern const char *regfile[];
extern char assembly[80];
extern int temu_state;
extern char asm_buf[128];

MyMainWindow::MyMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MyMainWindow)
{
    ui->setupUi(this);
    this->resize(1000, 800);
//=============================Prefab====================================
    ui->textText->setReadOnly(true);
    ui->goldenTraceText->setReadOnly(true);
    ui->regsText->setReadOnly(true);
    ui->statusText->setReadOnly(true);

//=============================related to run============================
    // single step
    connect(ui->onestepAction, &QAction::triggered, [=](){
        if(temu_state == END)
        {
            ui->textText->append(QString("Program execution has ended. To restart the program, exit TEMU and run again."));
            ui->goldenTraceText->append(QString("Program execution has ended. To restart the program, exit TEMU and run again."));
        }else
        {
            cpu_exec(1);
            // update regs
            ui->regsText->setText("");
            QString regInfo = QString("PC") + " = " + QString().sprintf("0x%08x", cpu.pc);
            ui->regsText->append(regInfo);
            int i;
            for(i = 0; i < 32; i ++) {
                QString regInfo = QString().sprintf("R%d[%s]\t= 0x%08x", i, regfile[i], cpu.gpr[i]._32);
                ui->regsText->append(regInfo);
            }

            // update golden trace
            ui->goldenTraceText->append(QString().sprintf("%08x\t%02d(%s)\t%08x", cpu.pc, op_dest->reg, REG_NAME(op_dest->reg), reg_w(op_dest->reg)));

            // to be replaced: text
            //QString textInfo = QString(assembly);
            QString textInfo = QString(asm_buf);
            ui->textText->append(textInfo);

            // to be repalced: data
//#ifdef __Qt_debug__
//            QString filePath = "../TEMU/log.txt";
//#else
//            QString filePath = "./TEMU/log.txt";
//#endif
//            if(filePath.isEmpty() == false)
//            {
//                QFile file(filePath);
//                if(file.open(QIODevice::ReadOnly))
//                {
//                    QTextCodec *pCodeBin = QTextCodec::codecForName("UTF-8");
//                    QByteArray array = file.readAll();
//                    QString arrayDst = pCodeBin->toUnicode(array);
//                    ui->goldenTraceText->setText(QString(arrayDst));
//                }else{
//                    QMessageBox::warning(this, tr("Read File"), "fail to open data.bin");
//                    perror("fail to open log.txt");
//                    return;
//                }
//            }else{
//                perror("fail to read log.txt");
//            }
        }

    });

    // run
    connect(ui->runAction, &QAction::triggered, [=](){
        while(temu_state != END)
        {
            cpu_exec(1);
            // update regs
            ui->regsText->setText("");
            QString regInfo = QString("PC") + " = " + QString().sprintf("0x%08x", cpu.pc);
            ui->regsText->append(regInfo);
            int i;
            for(i = 0; i < 32; i ++) {
                QString regInfo = QString().sprintf("R%d[%s]\t= 0x%08x", i, regfile[i], cpu.gpr[i]._32);
                ui->regsText->append(regInfo);
            }

            // to be replaced: text
            QString textInfo = QString(assembly);
            ui->textText->append(textInfo);
        }
    });

    // restart
    connect(ui->restartAction, &QAction::triggered, [=](){
       restart();
       temu_state = STOP;
       ui->textText->setText("");
       ui->goldenTraceText->setText("");
       ui->regsText->setText("");
       QString regInfo = QString("PC") + " = " + QString().sprintf("0x%08x", cpu.pc);
       ui->regsText->append(regInfo);
       int i;
       for(i = 0; i < 32; i ++) {
           cpu.gpr[i]._32 = 0;
           QString regInfo = QString().sprintf("R%d[%s]\t= 0x%08x", i, regfile[i], cpu.gpr[i]._32);
           ui->regsText->append(regInfo);
       }
    });

//=============================1_1_FP_regs===============================
//=============================1_2_regs==================================
    QString regInfo = QString("PC") + " = " + QString().sprintf("0x%08x", cpu.pc);
    ui->regsText->append(regInfo);
    int i;
    for(i = 0; i < 32; i ++) {
        QString regInfo = QString().sprintf("R%d[%s]\t= 0x%08x", i, regfile[i], cpu.gpr[i]._32);
        ui->regsText->append(regInfo);
    }

//=============================2_1_data_bin==============================
    // to be replaced
    connect(ui->loadDataAction, &QAction::triggered, [=](){
        QString filePath = QFileDialog::getOpenFileName(this, "open files", "/home/lvqq/MiniMips32/bin", "*.bin");
        if(filePath.isEmpty() == false)
        {
            QFile file(filePath);
            QFileInfo fileInfo(file);
            if(file.open(QIODevice::ReadOnly))
            {
//                QTextCodec *pCodeBin = QTextCodec::codecForName("US-ASCII");
//                QByteArray array = file.readAll();
//                QString arrayDst = pCodeBin->toUnicode(array);
//                ui->goldenTraceText->setText(QString(arrayDst));
                QDataStream binFileData(&file);
                char* binBuf = new char[fileInfo.size()];
                binFileData.readRawData(binBuf, static_cast<int>(fileInfo.size()));
                ui->goldenTraceText->setText(QString(binBuf));
            }else{
                QMessageBox::warning(this, tr("Read File"), "fail to open data.bin");
                perror("fail to open data.bin");
                return;
            }
        }else{
            perror("fail to read data.bin");
        }
        qDebug() << filePath;
    });


//=============================2_2_text_bin==============================
    // to be replaced
    connect(ui->loadTextAction, &QAction::triggered, [=](){
        QString filePath = QFileDialog::getOpenFileName(this, "open files", "/home/lvqq/MiniMips32/bin", "*.bin");
        if(filePath.isEmpty() == false)
        {
            QFile file(filePath);
            if(file.open(QIODevice::ReadOnly))
            {
                QTextCodec *pCodeBin = QTextCodec::codecForName("US-ASCII");
                QByteArray array = file.readAll();
                QString arrayDst = pCodeBin->toUnicode(array);
                ui->textText->setText(QString(arrayDst));
            }else{
                perror("fail to open inst.bin");
            }
        }else{
            perror("fail to read inst.bin");
        }
        qDebug() << filePath;
    });

//=============================3_statusText==============================
    ui->statusText->setTextColor(QColor("green"));
    ui->statusText->setText("everything is just right");
}

MyMainWindow::~MyMainWindow()
{
    delete ui;
}
